﻿/**
 *@description:
 *@file: break_out.cpp
 *@author: snow-tyan
 *@email: zziywang@163.com
 *@date: 20 March 2023
 *@copyright: 2018-2022 AiRiA. All rights reserved.
 */

#include <mygl/game/game.h>
#include <mygl/common/resource_manager.h>

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

using namespace mygl;
using namespace mygl::game;

// -------constant value--------
#ifdef _DEBUG
const std::string kGameLevelRoot = std::string(PROJECT_ROOT) + "/resources/levels/";
#else
const std::string kGameLevelRoot = "../resources/levels/";
#endif
const unsigned int kWindowWidth = 800;
const unsigned int kWindowHeight = 600;
const char* kWindowName = "Breakout";
// -------game global value-------
auto break_out = std::make_shared<Game>(kWindowWidth, kWindowHeight);
// ------call back functions------
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);
void FramebufferSizeCallback(GLFWwindow* window, int width, int height);

int main(int argc, char* argv[]) {
  glfwInit();
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

  GLFWwindow* window =
      glfwCreateWindow(kWindowWidth, kWindowHeight, kWindowName, nullptr, nullptr);
  glfwMakeContextCurrent(window);

  glfwSetKeyCallback(window, KeyCallback);
  glfwSetFramebufferSizeCallback(window, FramebufferSizeCallback);

  // --------glad: load all OpenGL function pointers--------
  if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
  }
#ifdef _DEBUG
  printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
  printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
  printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
  int max_attributes = 0;
  glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attributes);  // 硬件支持的最大顶点属性数量
  printf("Max number of vertex attribute supported: %d\n", max_attributes);
#endif
  // glEnable(GL_CULL_FACE);  // 启用面剔除
  glEnable(GL_BLEND);  // 启用混合
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  break_out->Init({
      kGameLevelRoot + "01-Standard.txt",
      kGameLevelRoot + "02-AFewSmallGaps.txt",
      kGameLevelRoot + "03-SpaceInvader.txt",
      kGameLevelRoot + "04-BounceGalore.txt",
  });

  float delta_time = 0.0f;  // 当前帧与上一帧的时间差
  float last_frame = 0.0f;  // 上一帧的时间

  break_out->set_game_state(GameState::ACTIVE);

  while (!glfwWindowShouldClose(window)) {
    // Calculate delta time
    float current_time = static_cast<float>(glfwGetTime());
    delta_time = current_time - last_frame;
    last_frame = current_time;

    // Manage user input
    break_out->ProcessInput(delta_time);

    // Update Game state
    break_out->Update(delta_time);

    // Render
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    break_out->Render(current_time);

    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  // Delete all resources as loaded using the resource manager
  ResourceManager::Clear();

  glfwTerminate();
  return 0;
}

void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode) {
  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
    glfwSetWindowShouldClose(window, GL_TRUE);
  }
  if (key >= 0 && key < 1024) {
    if (action == GLFW_PRESS) {
      break_out->keys[key] = GL_TRUE;
    } else if (action == GLFW_RELEASE) {
      break_out->keys[key] = GL_FALSE;
      break_out->keys_processed[key] = GL_FALSE;
    }
  }
}

void FramebufferSizeCallback(GLFWwindow* window, int width, int height) {
  glViewport(0, 0, width, height);
}